#include "uniCells.hpp"
#include "uniMesh.hpp"

namespace hms
{

UniCells::UniCells( const UniMesh& mesh ) :
	StructCellsBase<UniCells>(mesh)
{}


auto UniCells::area() const -> scalar {
	return m_area;
}

auto UniCells::circumf() const -> scalar {
	return m_circumf;
}

namespace uniCells_internal
{

auto centroids( const UniMesh& mesh, const Index& nxg, const Index& nyg )
	-> CentroidsExpressionType
{
	const scalar
		& dx { mesh.dx() },
		& dy { mesh.dy() },
		& x0 { mesh.origin().x() },
		& y0 { mesh.origin().y() };

	static constexpr Index ng {1};

	auto xCoords { RowVectorXs::LinSpaced( nxg, x0 + (0.5-ng)*dx, x0 + (nxg-ng-0.5)*dx ) };
	auto yCoords { RowVectorXs::LinSpaced( nyg, y0 + (0.5-ng)*dy, y0 + (nyg-ng-0.5)*dy ) };

	return concat_vertical(
		xCoords.replicate(1, nyg).reshaped().transpose(),
		yCoords.replicate(nxg, 1).reshaped().transpose()
	);
}

} // namespace internal



auto UniCells::centroidsImp() const -> CentroidsReturnType {
#ifdef UNIMESH_PRECALC_CENTROIDS
	return m_centroids;
#else
	return uniCells_internal::centroids( mesh(), m_nxg, m_nyg );
#endif
}

auto UniCells::areasImp() const -> AreasReturnType {
	return ArrayXs::Constant( m_outerSize, m_area );
}
auto UniCells::circumfsImp() const -> CircumfsReturnType {
	return ArrayXs::Constant( m_outerSize, m_circumf );
}

void UniCells::storeData(){
	m_area = mesh().diff().prod();
	m_circumf = 2*mesh().diff().sum();

	static constexpr Index ng {1};
	m_nxg = mesh().nCellsX()+2*ng;
	m_nyg = mesh().nCellsY()+2*ng;

	m_outerSize = m_nxg * m_nyg;
	
#ifdef UNIMESH_PRECALC_CENTROIDS
	m_centroids = uniCells_internal::centroids( mesh(), m_nxg, m_nyg );
#endif
}

} // namespace hms
